package parser;

import com.github.javaparser.ParseException;
import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.type.TypeParameter;
import com.thoughtworks.qdox.model.JavaClass;
import entity.ClassEntity;
import type.AccessModifierEnum;
import type.ClassTypeEnum;
import utils.ParserUtil;

import java.io.FileNotFoundException;
import java.util.*;

public class ClassParser {

    public static ClassEntity createClassEntity(JavaClass cls) throws ParseException {
        if (cls != null) {
            ClassEntity entity = new ClassEntity();
            // 类的全限定名，匿名类则为null
            entity.setName(cls.getFullyQualifiedName());
            // 类的代码(包括import)
            entity.setCode(getCode(cls));
            // 接口 or 类 or 注解 or 枚举
            entity.setClassTypeEnum(getClassType(cls));
            // 设置一般修饰符
            entity.setFinal(cls.isFinal());
            entity.setAbstract(cls.isAbstract());
            entity.setStatic(cls.isStatic());
            entity.setStrictfp(isStrictfp(cls.getModifiers()));
            // 设置访问修饰符
            entity.setAccessModifierEnum(getAccessModifier(cls));
            // 导入的包
            entity.setImports(cls.getSource().getImports());
            // 单继承父类
            entity.setSuperClass(cls.getSuperJavaClass());
            // 多实现接口
            entity.setInterfaces(cls.getInterfaces());
            // 构造器
            entity.setConstructors(cls.getConstructors());
            // 成员变量
            entity.setFields(cls.getFields());
            // 泛型声明/类型参数
            entity.setTypeParameters(getTypeParameters(cls));
            // 方法
            entity.setMethods(cls.getMethods());
            return entity;
        }
        throw new ParseException("创建类实体失败！");
    }

    public static String getCode(JavaClass cls) throws ParseException {
        ClassOrInterfaceDeclaration declaration = getClassOrInterfaceDeclaration(cls);
        if (declaration != null) {
            return declaration.toString();
        } else {
            return cls.getCodeBlock();
        }
    }

    /**
     * 泛型声明/类型参数
     */
    public static List<TypeParameter> getTypeParameters(JavaClass cls) throws ParseException {
        ClassOrInterfaceDeclaration declaration = getClassOrInterfaceDeclaration(cls);
        if (declaration != null) {
            return declaration.getTypeParameters();
        }
        return null;
    }

    /**
     * 使用 JavaParser 获取类对象 ClassOrInterfaceDeclaration
     * [已验证] 内部类，list.get(0) 始终获得的是外部主类
     * [fix]: 参见 ParserUtil.getFixedCode(String)
     */
    public static ClassOrInterfaceDeclaration getClassOrInterfaceDeclaration(JavaClass cls) throws ParseException {
        if (cls != null) {
            String fullyQualifiedName = cls.getFullyQualifiedName();
            CompilationUnit cu = null;
            List<ClassOrInterfaceDeclaration> list;
            if (!fullyQualifiedName.startsWith("java.") && !fullyQualifiedName.startsWith("jdk.")) {
                try {
                    cu = StaticJavaParser.parse(ParserUtil.getFileByClassName(cls.getFullyQualifiedName()));
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
            } else {
                String code = ParserUtil.getFixedCode(cls);
                if (code != null) {
                    cu = StaticJavaParser.parse(code);
                }
            }
            if (cu != null) {
                list = cu.findAll(ClassOrInterfaceDeclaration.class);
                if (list != null && !list.isEmpty()) {
                    return list.get(0);
                }
            }
            return null;
        }
        throw new ParseException("文件未找到！");
    }

    /**
     * 类的类型
     */
    public static ClassTypeEnum getClassType(JavaClass cls) throws ParseException {
        if (cls != null) {
            if (cls.isInterface()) {
                return ClassTypeEnum.INTERFACE;
            } else if (cls.isEnum()) {
                return ClassTypeEnum.ENUM;
            } else if (cls.isAnnotation()) {
                return ClassTypeEnum.ANNOTATION;
            } else {
                return ClassTypeEnum.CLASS;
            }
        }
        throw new ParseException("类为空！");
    }

    /**
     * 精确浮点关键字，可修饰类、接口、方法
     */
    public static boolean isStrictfp(List<String> modifiers) {
        return modifiers.contains("strictfp");
    }

    /**
     * 获取访问修饰符
     */
    public static AccessModifierEnum getAccessModifier(JavaClass cls) throws ParseException {
        if (cls != null) {
            if (cls.isPublic()) {
                return AccessModifierEnum.PUBLIC;
            } else if (cls.isPrivate()) {
                return AccessModifierEnum.PRIVATE;
            } else if (cls.isProtected()) {
                return AccessModifierEnum.PROTECTED;
            } else {
                return AccessModifierEnum.DEFAULT;
            }
        }
        throw new ParseException("类为空！");
    }

}
